package com.mazaiting.manager.config.mp.handler;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.mazaiting.common.core.ex.exceptions.EmptyObjectException;
import com.mazaiting.web.holder.SpringContextHolder;
import com.mazaiting.web.utils.UserUtil;
import com.mazaiting.manager.config.mp.annos.DeptPermission;
import com.mazaiting.manager.constant.SystemConstant;
import com.mazaiting.manager.mapper.ISysDeptMapper;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.schema.Column;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * 部门权限处理器
 *
 * @author mazaiting
 * @create_time 2022/9/24 19:13
 */
@Slf4j
public class DeptPermissionHandler implements DataPermissionHandler {

//    private final ISysDeptMapper sysDeptMapper;

    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        try {
            // 加载类
            Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(".")));
            // 获取方法名
            String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(".") + 1);
            // 获取定义的方法
            Method[] methods = clazz.getDeclaredMethods();
            // 遍历方法
            for (Method method : methods) {
                // 获取注解, 获取别名需要
                DeptPermission deptPermission = AnnotationUtils.findAnnotation(method, DeptPermission.class);
                if (ObjectUtils.isNotEmpty(deptPermission) && Objects.equals(method.getName(), methodName)) {
                    // 获取当前的用户角色
                    List<String> roles = UserUtil.getRoles();
                    if (!roles.isEmpty() && roles.contains(SystemConstant.ROOT_ROLE_CODE)) {
                        // 如果是超级管理员则放行
                        return where;
                    } else {
                        return dataScopeFilter(deptPermission.tableName(), where);
                    }
                }
            }
        } catch (Exception e) {
            log.error("部门权限处理异常: " + e.getMessage());
            e.printStackTrace();
        }
        return where;
    }

    /**
     * 构建过滤条件
     *
     * @param where 当前查询条件
     * @return 构建后查询条件
     */
    public Expression dataScopeFilter(String deptAlias, Expression where) throws EmptyObjectException {
        // 获取部门 ID 及子部门
        ExpressionList deptIdExpList = getDeptId();
        // sd.id in (exp1, exp2, exp3...)
        InExpression inExpression = new InExpression(new Column(StringUtils.hasLength(deptAlias) ? deptAlias + ".id" : "id"), deptIdExpList);
        // 如果 where 条件不为空, 则使用 and 表达式
        return ObjectUtils.isNotEmpty(where) ? new AndExpression(where, inExpression) : inExpression;
    }

    /**
     * 当前用户的部门 ID 及子部门
     *
     * @return 当前用户的部门 ID 表达式列表
     */
    private ExpressionList getDeptId() throws EmptyObjectException {
        // 获取部门数据库操作工具
        ISysDeptMapper sysDeptMapper = SpringContextHolder.getBean(ISysDeptMapper.class);
        // 部门 ID 及子部门
        List<Long> idList = sysDeptMapper.findByParentId(UserUtil.getDeptId());
        ExpressionList expList = new ExpressionList();
        idList.forEach(id -> expList.addExpressions(new LongValue(id)));
        return expList;
    }


//    /**
//     * 构建过滤条件
//     *
//     * @param where 当前查询条件
//     * @return 构建后查询条件
//     */
//    public static Expression dataScopeFilter(String deptAlias, Expression where) throws EmptyObjectException {
//        // 部门 ID
//        Expression deptIdExp = getDeptId();
//        Expression expression = new EqualsTo(new Column(StrUtil.isEmpty(deptAlias) ? "id" : deptAlias + ".id"), deptIdExp);
//        LikeExpression likeExpression = new LikeExpression();
//        Function left = new Function();
//        left.setName("concat");
//        left.setParameters(new ExpressionList().addExpressions(new StringValue(","), new Column("tree_path"), new StringValue(",")));
//        likeExpression.setLeftExpression(left);
//        Function right = new Function();
//        right.setName("concat");
//        right.setParameters(new ExpressionList().addExpressions(new StringValue("%,"), deptIdExp, new StringValue("%,")));
//        likeExpression.setRightExpression(right);
//        expression = ObjectUtils.isNotEmpty(expression) ? new OrExpression(expression, likeExpression) : expression;
//
//        return ObjectUtils.isNotEmpty(where) ? new AndExpression(where, new Parenthesis(expression)) : expression;
//    }

}
